#include "ElaSliderRange.h"
#define SLIDER_HANDLE_RADIUS 9 // 滑块外圆半径
#define SLIDER_BAR_HEIGHT 5 // 滑槽高度
#define SLIDER_CORNER_RADIUS 2 // 滑槽圆角半径
#define SLIDER_ANIMATION_DURATION 150 // 动画持续时间（毫秒）
#define SLIDER_MIN_RADIUS 4 // 滑块内圆最小半径（按下时）
#define SLIDER_DEFAULT_RADIUS 5 // 滑块内圆默认半径
#define SLIDER_MAX_RADIUS 6.5 // 滑块内圆最大半径（悬停时）

// 构造函数
ElaSliderRange::ElaSliderRange(Qt::Orientation orientation, QWidget* parent)
    : QSlider(orientation, parent), _leftValue(25), _rightValue(75), _movingLeft(false), _movingRight(false), _lastMovedLeft(true) {
    setRange(0, 100);
    setMouseTracking(true);
    setAttribute(Qt::WA_Hover, true);
    if (orientation == Qt::Horizontal) {
        setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Fixed);
        setMinimumHeight(2 * SLIDER_HANDLE_RADIUS + 3);
    } else {
        setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Expanding);
        setMinimumWidth(2 * SLIDER_HANDLE_RADIUS + 3);
    }

    _leftCircleRadius = SLIDER_DEFAULT_RADIUS;
    _rightCircleRadius = SLIDER_DEFAULT_RADIUS;
    _themeMode = eTheme->getThemeMode();

    connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
        _themeMode = themeMode;
        update();
    });
}

ElaSliderRange::~ElaSliderRange() {}

// 绘制滑块组件
void ElaSliderRange::paintEvent(QPaintEvent* event) {
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    QRect sliderRect = rect();

    // 计算滑槽位置（居中显示）
    const int barHeight = SLIDER_BAR_HEIGHT;
    const int barY = (sliderRect.height() - barHeight) / 2;

    // 绘制滑槽（未滑过部分）
    painter.setPen(Qt::NoPen);
    painter.setBrush(ElaThemeColor(_themeMode, BasicChute));
    painter.drawRoundedRect(QRect(sliderRect.x(), barY, sliderRect.width(), barHeight), SLIDER_CORNER_RADIUS, SLIDER_CORNER_RADIUS);

    // 计算滑块位置
    qreal minX = SLIDER_HANDLE_RADIUS + 0.5;
    qreal maxX = width() - SLIDER_HANDLE_RADIUS - 0.5;
    qreal leftPos = qBound(minX, (qreal)QStyle::sliderPositionFromValue(minimum(), maximum(), _leftValue, width()), maxX);
    qreal rightPos = qBound(minX, (qreal)QStyle::sliderPositionFromValue(minimum(), maximum(), _rightValue, width()), maxX);

    // 绘制已滑过部分
    painter.setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
    QRect passedRect(leftPos, barY, rightPos - leftPos, barHeight);
    painter.drawRoundedRect(passedRect, SLIDER_CORNER_RADIUS, SLIDER_CORNER_RADIUS);

    // 绘制滑块
    const int handleY = barY + barHeight / 2;
    auto drawHandle = [&](qreal pos, bool isLeft) {
        QPointF handleCenter(pos, handleY);
        painter.setPen(ElaThemeColor(_themeMode, BasicBorder));
        painter.setBrush(ElaThemeColor(_themeMode, BasicBase));
        painter.drawEllipse(handleCenter, qreal(SLIDER_HANDLE_RADIUS), qreal(SLIDER_HANDLE_RADIUS));

        painter.setPen(Qt::NoPen);
        painter.setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
        const qreal radius = isLeft ? _leftCircleRadius : _rightCircleRadius;
        painter.drawEllipse(handleCenter, radius, radius);
    };

    // 先绘制非最后拖动的滑块，再绘制最后拖动的滑块（确保最后拖动的滑块在上方）
    if (_lastMovedLeft) {
        drawHandle(rightPos, false);
        drawHandle(leftPos, true);
    } else {
        drawHandle(leftPos, true);
        drawHandle(rightPos, false);
    }
}

// 鼠标按下事件
void ElaSliderRange::mousePressEvent(QMouseEvent* event) {
    int pos = event->pos().x();
    int leftPos = QStyle::sliderPositionFromValue(minimum(), maximum(), _leftValue, width());
    int rightPos = QStyle::sliderPositionFromValue(minimum(), maximum(), _rightValue, width());
    // 优先检查最后拖动的滑块
    if (_lastMovedLeft) {
        if (abs(pos - leftPos) < SLIDER_HANDLE_RADIUS) {
            _movingLeft = true;
            _startRadiusAnimation(_leftCircleRadius, SLIDER_MIN_RADIUS, true);
            return;
        }
        if (abs(pos - rightPos) < SLIDER_HANDLE_RADIUS) {
            _movingRight = true;
            _lastMovedLeft = false;
            _startRadiusAnimation(_leftCircleRadius, SLIDER_MIN_RADIUS, false);
            return;
        }
    } else {
        if (abs(pos - rightPos) < SLIDER_HANDLE_RADIUS) {
            _movingRight = true;
            _startRadiusAnimation(_rightCircleRadius, SLIDER_MIN_RADIUS, false);
            return;
        }
        if (abs(pos - leftPos) < SLIDER_HANDLE_RADIUS) {
            _movingLeft = true;
            _lastMovedLeft = true;
            _startRadiusAnimation(_rightCircleRadius, SLIDER_MIN_RADIUS, true);
            return;
        }
    }
    // 点击位置在滑块外
    int disLeft = abs(pos - leftPos);
    int disRight = abs(pos - rightPos);
    int val = QStyle::sliderValueFromPosition(minimum(), maximum(), pos, width());
    if(disLeft < disRight || (disLeft == disRight && pos < leftPos)) {
        _leftValue = qMax(val, minimum());
        _movingLeft = true;
        _movingRight = false;
        _lastMovedLeft = true;
    }
    if(disLeft > disRight || (disLeft == disRight && pos > rightPos)) {
        _rightValue = qMin(val, maximum());
        _movingLeft = false;
        _movingRight = true;
        _lastMovedLeft = false;
    }
    update();
}


// 鼠标拖动事件
void ElaSliderRange::mouseMoveEvent(QMouseEvent* event) {
    int pos = QStyle::sliderValueFromPosition(minimum(), maximum(), event->pos().x(), width());
    if (_movingLeft && pos <= _rightValue) { // 允许两个滑块相等
        _leftValue = qMax(pos, minimum());
    } else if (_movingRight && pos >= _leftValue) {
        _rightValue = qMin(pos, maximum());
    }

    // 计算滑块位置
    int leftPos = QStyle::sliderPositionFromValue(minimum(), maximum(), _leftValue, width());
    int rightPos = QStyle::sliderPositionFromValue(minimum(), maximum(), _rightValue, width());

    bool newHoverLeft =  (abs(event->pos().x() - leftPos) <= SLIDER_HANDLE_RADIUS && abs(event->pos().y() - SLIDER_HANDLE_RADIUS) <= SLIDER_HANDLE_RADIUS);
    bool newHoverRight = (abs(event->pos().x() - rightPos) <= SLIDER_HANDLE_RADIUS && abs(event->pos().y() - SLIDER_HANDLE_RADIUS) <= SLIDER_HANDLE_RADIUS);

    // 检测左滑块悬停变化
    if (newHoverLeft && !_hoverLeft) {
        _hoverLeft = true;
        if(!_movingLeft)
            _startRadiusAnimation(_leftCircleRadius, SLIDER_MAX_RADIUS, true);
    } else if (!newHoverLeft && _hoverLeft) {
        _hoverLeft = false;
        if(!_movingLeft)
            _startRadiusAnimation(_leftCircleRadius, SLIDER_DEFAULT_RADIUS, true);
    }

    // 检测右滑块悬停变化
    if (newHoverRight && !_hoverRight) {
        _hoverRight = true;
        if(!_movingRight)
        _startRadiusAnimation(_rightCircleRadius, SLIDER_MAX_RADIUS, false);
    } else if (!newHoverRight && _hoverRight) {
        _hoverRight = false;
        if(!_movingRight)
        _startRadiusAnimation(_rightCircleRadius, SLIDER_DEFAULT_RADIUS, false);
    }

    update();
}

//鼠标离开事件
void ElaSliderRange::leaveEvent(QEvent* event) {
    Q_UNUSED(event);
    if (_hoverLeft && !_movingLeft) {
        _startRadiusAnimation(_leftCircleRadius, SLIDER_DEFAULT_RADIUS, true);
    }

    if (_hoverRight && !_movingRight) {
        _startRadiusAnimation(_rightCircleRadius, SLIDER_DEFAULT_RADIUS, false);
    }
    _hoverLeft = _hoverRight = false;
}

// 鼠标释放事件
void ElaSliderRange::mouseReleaseEvent(QMouseEvent* event) {
    Q_UNUSED(event);
    if (_movingLeft) _startRadiusAnimation(_leftCircleRadius, _hoverLeft ? SLIDER_MAX_RADIUS : SLIDER_DEFAULT_RADIUS, true);
    if (_movingRight) _startRadiusAnimation(_rightCircleRadius, _hoverRight ? SLIDER_MAX_RADIUS : SLIDER_DEFAULT_RADIUS, false);
    _movingLeft = false;
    _movingRight = false;
    emit valueChanged(_leftValue, _rightValue);
}

// 滚轮监听事件
void ElaSliderRange::wheelEvent(QWheelEvent* event) {
    event->accept();
    int delta = event->angleDelta().y() > 0 ? 1 : -1; // 获取滚轮方向（上滚+1，下滚-1）
    int mouseX = event->position().x(); // 获取鼠标位置

    // 计算滑块的像素位置
    int minX = SLIDER_HANDLE_RADIUS;
    int maxX = width() - SLIDER_HANDLE_RADIUS;
    int leftPos = qBound(minX, QStyle::sliderPositionFromValue(minimum(), maximum(), _leftValue, width()), maxX);
    int rightPos = qBound(minX, QStyle::sliderPositionFromValue(minimum(), maximum(), _rightValue, width()), maxX);

    // 计算鼠标到滑块的距离
    int leftDistance = abs(mouseX - leftPos);
    int rightDistance = abs(mouseX - rightPos);

    // 选择最近的滑块
    if (event->modifiers() & Qt::ControlModifier) {
        _leftValue = qBound(minimum(), _leftValue + delta, _rightValue);
        _rightValue = qBound(_leftValue, _rightValue + delta, maximum());
    }
    else if (leftDistance < rightDistance) {
        // 调整左滑块，确保不超过右滑块
        _leftValue = qBound(minimum(), _leftValue + delta, _rightValue);
    } else {
        // 调整右滑块，确保不小于左滑块
        _rightValue = qBound(_leftValue, _rightValue + delta, maximum());
    }
    emit valueChanged(_leftValue, _rightValue);
    update(); // 触发重绘
}


// 启动滑块动画
void ElaSliderRange::_startRadiusAnimation(qreal startRadius, qreal endRadius, bool isLeft) {
    QPropertyAnimation* animation = new QPropertyAnimation(this, isLeft ? "leftCircleRadius" : "rightCircleRadius");
    connect(animation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
        if (isLeft) {
            _leftCircleRadius = value.toReal();
        } else {
            _rightCircleRadius = value.toReal();
        }
        update();
    });
    animation->setEasingCurve(QEasingCurve::InOutSine);
    animation->setStartValue(startRadius);
    animation->setEndValue(endRadius);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
}

void ElaSliderRange::setRange(int left, int right) {
    // 设置滑块的范围
    QSlider::setRange(left, right);
    // 确保左值和右值在范围内
    _leftValue = qBound(left, _leftValue, right);
    _rightValue = qBound(left, _rightValue, right);
    emit valueChanged(_leftValue, _rightValue);
    update(); // 触发重绘
}

void ElaSliderRange::setValue(int left, int right) {
    // 确保左值和右值在范围内
    left = qBound(minimum(), left, maximum());
    right = qBound(minimum(), right, maximum());
    if(left > right)
        return;
    _leftValue = left;
    _rightValue = right;
    emit valueChanged(_leftValue, _rightValue);
    update(); // 触发重绘
}

void ElaSliderRange::setLeftValue(int value) {
    if (value > _rightValue) return; // 确保左滑块不会超过右滑块
    _leftValue = qBound(minimum(), value, maximum());
    emit valueChanged(_leftValue, _rightValue);
    update();
}

void ElaSliderRange::setRightValue(int value) {
    if (value < _leftValue) return; // 确保右滑块不会小于左滑块
    _rightValue = qBound(minimum(), value, maximum());
    emit valueChanged(_leftValue, _rightValue);
    update();
}

int ElaSliderRange::getLeftValue() {
    return _leftValue;
}

int ElaSliderRange::getRightValue() {
    return _rightValue;
}
